﻿#pragma once

#include "../MirEnvir/Envir.h"
#include "../../Shared/Data/GuildData.h"
#include "../../Shared/Data/Notice.h"
#include "ConquestObject.h"
#include "PlayerObject.h"
#include "../../Shared/Enums.h"
#include "../../Shared/Packet.h"
#include "../../Shared/Data/ItemData.h"
#include <string>
#include <vector>
#include <limits>
#include <any>
#include "../../stringhelper.h"

using namespace Server::MirEnvir;

namespace Server::MirObjects
{
    class GuildObject
    {
    public:
        virtual ~GuildObject()
        {
            delete FlagColour;
            delete Conquest;
        }

    protected:
        static Server::MirEnvir::Envir *getEnvir();

    public:
        int Guildindex = 0;
        std::string Name = "";
        unsigned char Level = 0;
        unsigned char SparePoints = 0;
        long long Experience = 0;
        unsigned int Gold = 0;
        std::vector<GuildRank*> Ranks = std::vector<GuildRank*>();
        std::vector<GuildStorageItem*> StoredItems = std::vector<GuildStorageItem*>(112);
        std::vector<GuildBuff*> BuffList = std::vector<GuildBuff*>();
        int Votes = 0;
        DateTime LastVoteAttempt;
        bool Voting = false;
        bool NeedSave = false;
        int Membercount = 0;
        long long MaxExperience = 0;
        long long NextExpUpdate = 0;
        int MemberCap = 0;
        std::vector<std::string> Notice = std::vector<std::string>();
        std::vector<GuildObject*> WarringGuilds = std::vector<GuildObject*>();

        unsigned short FlagImage = 1000;
        Color *FlagColour = Color::White;

        ConquestObject *Conquest;

        std::vector<GuildObject*> AllyGuilds = std::vector<GuildObject*>();
        int AllyCount = 0;


        GuildObject();
        GuildObject(PlayerObject *owner, const std::string &name);

        GuildObject(BinaryReader *reader);
        void Save(BinaryWriter *writer);

        void SendMessage(const std::string &message, ChatType Type = ChatType::Guild);

        void SendOutputMessage(const std::string &message, OutputMessageType Type = OutputMessageType::Guild);

        std::vector<PlayerObject*> GetOnlinePlayers();

        void PlayerLogged(PlayerObject *member, bool online, bool New = false);

        void SendGuildStatus(PlayerObject *member);

        void NewMember(PlayerObject *newMember);

        bool ChangeRank(PlayerObject *self, const std::string &memberName, unsigned char rankIndex, const std::string &rankName = "Members");

        bool NewRank(PlayerObject *Self);

        bool ChangeRankOption(PlayerObject *Self, unsigned char RankIndex, int Option, const std::string &Enabled);
        bool ChangeRankName(PlayerObject *Self, const std::string &RankName, unsigned char RankIndex);

        bool DeleteMember(PlayerObject *Kicker, const std::string &membername);

        void MemberDeleted(const std::string &name, PlayerObject *formerMember, bool kickSelf);

        GuildRank *FindRank(const std::string &name);
        void NewNotice(std::vector<std::string> &notice);

        void SendServerPacket(Packet *p);

        void SendItemInfo(UserItem *Item);

        bool HasRoom();
        void GainExp(unsigned int amount);


        #pragma region Guild Wars

        bool GoToWar(GuildObject *enemyGuild);

            getEnvir()->GuildsAtWar.push_back(new GuildAtWar(this, enemyGuild));
            UpdatePlayersColours();
            enemyGuild::UpdatePlayersColours();
        private:
            return *true;
    };

    public:
        void UpdatePlayersColours();

        bool IsAtWar();

        std::string GetName();

        bool IsEnemy(GuildObject *enemyGuild);
        #pragma endregion

        void RefreshAllStats();


        void Process();

        GuildBuff *GetBuff(int Id);

        void NewBuff(int Id, bool charge = true);

    private:
        void ChargeForBuff(GuildBuff *buff);

    public:
        void ActivateBuff(int Id);
        void RemoveAllBuffs();

}

    class GuildAtWar
    {
    public:
        GuildObject *GuildA;
        GuildObject *GuildB;
        long long TimeRemaining = 0;

        GuildAtWar(GuildObject *a, GuildObject *b);

        void EndWar();
    };

    class GuildItemVolume
    {
    public:
        ItemInfo *Item;
        std::string ItemName;
        unsigned int Amount = 0;
    };
}
